package com.zam.web.controller;

import com.auth0.jwt.JWT;

import com.zam.comment.Result;
import com.zam.service.IUserExtendService;
import com.zam.utils.DateUtil.DateTransformUtil;
import com.zam.utils.IntegralUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.zam.comment.Constants.CODE_600;
import static com.zam.comment.Constants.USER_CHECKIN_KEY;


/**
 * @Author talent_dog
 * @Date 2024/1/4 18:26
 * @Version 1.0
 */
@RestController
@RequestMapping("/checkin")
public class CheckinController {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private IUserExtendService userExtendService;

    @GetMapping("/signIn/{day}")
    public Result checkin(@PathVariable("day") String day, HttpServletRequest request) {
        HashMap<String, Object> hashMap = redisDataKey(day);
        LocalDateTime dayDateTime = (LocalDateTime) hashMap.get("dayDateTime");
        Integer dayInt = (Integer) hashMap.get("dayInt");
        String format = (String) hashMap.get("format");

        int dayOfYearInt = dayDateTime.getYear() << 9 | dayDateTime.getDayOfYear();

        //获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 2.获取今天是当月的第几天
        int nowOfYearInt = now.getYear() << 9 | now.getDayOfYear();

        //获取token，当Redis中的key
        String token = request.getHeader("token");
        String userId = JWT.decode(token).getAudience().get(0);

        // 1.获取当前时间
        String key = USER_CHECKIN_KEY + userId + ":" + format;

        // 4.判断是否签到过
        Boolean bit = stringRedisTemplate.opsForValue().getBit(key, dayInt - 1);
        if (bit) {
            return Result.error(CODE_600, "已经签到");
        }
        // 5.签到
        if (dayOfYearInt == nowOfYearInt) {
            stringRedisTemplate.opsForValue().setBit(key, dayInt - 1, true);

            //自定义方法，当日签到，积分+5
            IntegralUtil.normalCheckin(Integer.parseInt(userId));
            return Result.success("签到成功,积分+5");
        } else if (dayOfYearInt < nowOfYearInt) {
            stringRedisTemplate.opsForValue().setBit(key, dayInt - 1, true);

            //自定义方法，补签，积分+2
            IntegralUtil.afterCheckin(Integer.parseInt(userId));
            return Result.success("补签成功,积分+2");
        }
        return Result.error(CODE_600, "签到失败");
    }

    @GetMapping("/signCount/{day}")
    public Result signCount(@PathVariable("day") String day, HttpServletRequest request) {
        String token = request.getHeader("token");
        String userId = JWT.decode(token).getAudience().get(0);
        LocalDateTime dayDateTime = null;
        try {
            //将字符串转换为LocalDateTime类型日期
            dayDateTime = DateTransformUtil.stringToDataSimple(day);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        int year = dayDateTime.getYear();
        int month = dayDateTime.getMonth().getValue();
        //key中符号
        String symbol = ":";
        if (month < 10) {
            symbol = ":0";
        }
        //今日时间
        LocalDateTime now = LocalDateTime.now();
        int year1 = now.getYear();
        int month1 = now.getMonth().getValue();
        int dayOfMonth = now.getDayOfMonth();

        String key = USER_CHECKIN_KEY + userId + ":" + year + symbol + month;
        HashMap<String, Long> Datacount = new HashMap<>();
        if (year == year1 && month == month1) {
            //月份年份相等
            List<Long> longs = stringRedisTemplate.opsForValue()
                    .bitField(key, BitFieldSubCommands.create()
                            .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
            Long l = longs.get(0);
            Long count = count(l);
            Long continuosCount = continuosCount(l);

            Datacount.put("monthSign", count);
            Datacount.put("signCount", continuosCount);

        } else {
            //不相等
            Long count = continuosCount(key);
            Datacount.put("monthSign", count);
        }
        Long yearCount = 0L;
        String yearkey = "";
        for (int i = 1; i <= 12; i++) {
            yearkey = USER_CHECKIN_KEY + userId + ":" + year;
            symbol = ":";
            if (i < 10) {
                symbol = ":0";
            }
            yearkey = yearkey + symbol + i;
            yearCount += continuosCount(yearkey);
        }
        Datacount.put("yearSign", yearCount);
        return Result.success(Datacount);
    }

    //季度签到统计
    @GetMapping("/quarterData/{year}")
    public Result quarterData(@PathVariable("year") String year, HttpServletRequest request) {
        String token = request.getHeader("token");
        String userId = JWT.decode(token).getAudience().get(0);
        String quarterKey = "";
        String symbol = "";
        List<Long> list = new ArrayList<>();
        Long quarter1 = 0l;
        Long quarter2 = 0l;
        Long quarter3 = 0l;
        Long quarter4 = 0l;
        for (int i = 1; i <= 12; i++) {
            quarterKey = USER_CHECKIN_KEY + userId + ":" + year;
            symbol = ":";
            switch (i) {
                case 12:
                case 1:
                case 2:
                    if (i != 12) {
                        symbol = ":0";
                    }
                    quarterKey = quarterKey + symbol + i;
                    quarter1 += continuosCount(quarterKey);
                    break;
                case 3:
                case 4:
                case 5:
                    symbol = ":0";
                    quarterKey = quarterKey + symbol + i;
                    quarter2 += continuosCount(quarterKey);
                    break;
                case 6:
                case 7:
                case 8:
                    symbol = ":0";
                    quarterKey = quarterKey + symbol + i;
                    quarter3 += continuosCount(quarterKey);
                    break;
                case 9:
                case 10:
                case 11:
                    if (i == 9) {
                        symbol = ":0";
                    }
                    quarterKey = quarterKey + symbol + i;
                    quarter4 += continuosCount(quarterKey);
                    break;
                default:
                    break;
            }
        }
        Collections.addAll(list, quarter1, quarter2, quarter3, quarter4);
        return Result.success(list);
    }

    //判断是否签到
    @GetMapping("/isCheckin/{day}")
    public Result ischeckin(@PathVariable("day") String day, HttpServletRequest request) {
        //获取token，当Redis中的key
        String token = request.getHeader("token");
        String userId = JWT.decode(token).getAudience().get(0);

        //处理前端日期信息
        HashMap<String, Object> stringObjectHashMap = redisDataKey(day);
        Integer dayInt = (Integer) stringObjectHashMap.get("dayInt");
        String format = (String) stringObjectHashMap.get("format");

        Boolean bit = stringRedisTemplate.opsForValue().getBit(USER_CHECKIN_KEY + userId + ":" + format, dayInt - 1);
        if (bit) {
            //返回数据1，表示今日签到成功
            return Result.success(1);
        }
        return Result.success();
    }

    //将前端传过来的日期进行数据的获取
    private HashMap<String, Object> redisDataKey(String day) {
        HashMap<String, Object> hashMap = new HashMap<>();
        LocalDateTime dayDateTime = null;
        try {
            //将字符串转换为LocalDateTime类型日期
            dayDateTime = DateTransformUtil.stringToData(day);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //前端日期是当月的第几天
        Integer dayInt = dayDateTime.getDayOfMonth();
        //前端日期当年当月的日期转为字符串
        String format = dayDateTime.format(DateTimeFormatter.ofPattern("yyyy:MM"));

        hashMap.put("dayDateTime", dayDateTime);
        hashMap.put("dayInt", dayInt);
        hashMap.put("format", format);
        return hashMap;
    }

    private Long count(Long num) {
        Long count = 0L;
        while (true) {
            if (((num & 1) == 1)) {
                count++;
            }
            num >>>= 1;
            if (num == 0) {
                break;
            }
        }
        return count;
    }

    private Long continuosCount(Long num) {
        Long count = 0L;
        while (true) {
            if (((num & 1) == 0)) {
                break;
            } else {
                count++;
            }
            num >>>= 1;
        }
        return count;
    }

    private Long continuosCount(String key) {
        List<Long> longs = stringRedisTemplate.opsForValue()
                .bitField(key, BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(31)).valueAt(0));
        Long l = longs.get(0);
        Long count = count(l);
        return count;
    }

}
